/**  
 * All rights Reserved, Designed By www.flksh.com
 * @date:   2017-10-26 15:32:46   
 * @Copyright: 2013-2017 www.flksh.com Inc. All rights reserved. 
 * 注意：本内容仅限于上海福乐康社区养老服务有限公司内部传阅，禁止外泄以及用于其他的商业目
 */
package com.zx.cloud.service;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.annotation.PostConstruct;

import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.zx.cloud.domain.ScheduleJob;
import com.zx.cloud.domain.ScheduleJobHistory;
import com.zx.cloud.job.QuartzJobFactory;
import com.zx.cloud.lisenter.DaemonSchedulerListener;
import com.zx.cloud.lisenter.DaemonTriggerListener;
//gitee.com/markyu/zx-cloud.git
import com.zx.cloud.persistence.CrudMapper;
import com.zx.cloud.persistence.ScheduleJobHistoryMapper;
import com.zx.cloud.util.DateTimeUtil;

/**
 * 定时任务
 */
@Service
public class ScheduleJobService extends CrudServiceImpl<ScheduleJob> {

	@Autowired
	private Scheduler scheduler;
	@Autowired
	private DaemonSchedulerListener daemonSchedulerListener;
	@Autowired
	private DaemonTriggerListener daemonTriggerListener;

	@PostConstruct
	public void init() throws SchedulerException {
		scheduler.getListenerManager().addSchedulerListener(daemonSchedulerListener);
		scheduler.getListenerManager().addTriggerListener(daemonTriggerListener);
	}

	@Autowired
	private ScheduleJobHistoryMapper scheduleJobHistoryMapper;

	@Autowired
	public ScheduleJobService(CrudMapper<ScheduleJob> mapper) {
		super(mapper);
	}

	/**
	 * 添加定时任务
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean add(ScheduleJob scheduleJob) throws ClassNotFoundException, SchedulerException {
		ScheduleJob findScheduleJob = new ScheduleJob();
		findScheduleJob.setClassName(scheduleJob.getClassName());
		findScheduleJob.setMethodName(scheduleJob.getMethodName());
		long count = mapper.count(findScheduleJob);
		if (count == 0) {
			if (mapper.insert(scheduleJob) > 0) {
				JobDetail jobDetail = JobBuilder.newJob(QuartzJobFactory.class).withDescription(scheduleJob.getDescription())
						.usingJobData("description", scheduleJob.getDescription()).usingJobData("className", scheduleJob.getClassName())
						.usingJobData("methodName", scheduleJob.getMethodName())
						.usingJobData("createTime",DateTimeUtil.formatDateTimetoString(new Date())).withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup()).build();
				jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);
				// 表达式调度构建器（可判断创建SimpleScheduleBuilder）
				CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(scheduleJob.getCronExpression());
				// 按新的cronExpression表达式构建一个新的trigger
				CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(scheduleJob.getJobName(), scheduleJob.getJobGroup())
						.withSchedule(scheduleBuilder).build();
				scheduler.scheduleJob(jobDetail, trigger);
			}
		}
		return true;
	}

	/**
	 * 获取所有JobDetail
	 */
	public List<JobDetail> getJobs() throws SchedulerException {
		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
		Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
		List<JobDetail> jobDetails = new ArrayList<JobDetail>();
		for (JobKey key : jobKeys) {
			jobDetails.add(scheduler.getJobDetail(key));
		}
		return jobDetails;
	}

	/**
	 * 获取所有计划中的任务
	 */
	public List<ScheduleJob> getAllScheduleJob() throws SchedulerException {
		List<ScheduleJob> scheduleJobList = new ArrayList<ScheduleJob>();
		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
		Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
		Set<String> values=new HashSet<String>();
		for (JobKey jobKey : jobKeys) {
			List<? extends Trigger> triggers = scheduler.getTriggersOfJob(jobKey);
			for (Trigger trigger : triggers) {
				ScheduleJob scheduleJob = new ScheduleJob();
				scheduleJob.setJobName(jobKey.getName());
				scheduleJob.setJobGroup(jobKey.getGroup());
				Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
				scheduleJob.setStatus(triggerState.name());
				// 获取要执行的定时任务类名
				JobDetail jobDetail = scheduler.getJobDetail(jobKey);
				// 获取class及method
				JobDataMap dataMap = jobDetail.getJobDataMap();
				scheduleJob.setClassName(dataMap.getString("className"));
				scheduleJob.setMethodName(dataMap.getString("methodName"));
				scheduleJob.setCreateTimeStr(dataMap.getString("createTime"));
				// 判断trigger
				if (trigger instanceof SimpleTrigger) {
					SimpleTrigger simple = (SimpleTrigger) trigger;
					scheduleJob.setPreviousFireTime(DateTimeUtil.formatDateTimetoString(simple.getPreviousFireTime()));
					scheduleJob.setNextFireTime(DateTimeUtil.formatDateTimetoString(simple.getNextFireTime()));
					scheduleJob.setCronExpression(
							"重复次数:" + (simple.getRepeatCount() == -1 ? "无限" : simple.getRepeatCount()) + ",重复间隔:" + (simple.getRepeatInterval() / 1000L));
					scheduleJob.setDescription(simple.getDescription());
				}
				if (trigger instanceof CronTrigger) {
					CronTrigger cron = (CronTrigger) trigger;
					scheduleJob.setPreviousFireTime(DateTimeUtil.formatDateTimetoString(cron.getPreviousFireTime()));
					scheduleJob.setNextFireTime(DateTimeUtil.formatDateTimetoString(cron.getNextFireTime()));
					scheduleJob.setCronExpression(cron.getCronExpression());
					scheduleJob.setDescription(cron.getDescription() == null ? ("触发器:" + trigger.getKey()) : cron.getDescription());
				}
				if(!values.contains(jobKey.getGroup()+jobKey.getName())){
					scheduleJobList.add(scheduleJob);
					values.add(jobKey.getGroup()+jobKey.getName());
				}
			}
		}
		return scheduleJobList;
	}

	/**
	 * 获取所有运行中的任务
	 */
	public List<ScheduleJob> getAllRuningScheduleJob() throws SchedulerException {
		List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
		List<ScheduleJob> scheduleJobList = new ArrayList<ScheduleJob>(executingJobs.size());
		for (JobExecutionContext executingJob : executingJobs) {
			ScheduleJob scheduleJob = new ScheduleJob();
			JobDetail jobDetail = executingJob.getJobDetail();
			JobKey jobKey = jobDetail.getKey();
			Trigger trigger = executingJob.getTrigger();
			scheduleJob.setJobName(jobKey.getName());
			scheduleJob.setJobGroup(jobKey.getGroup());
			// ScheduleJob.setDescription("触发器:" + trigger.getKey());
			Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
			scheduleJob.setStatus(triggerState.name());
			// 获取要执行的定时任务类名
			scheduleJob.setClassName(jobDetail.getJobClass().getName());
			// 判断trigger
			if (trigger instanceof SimpleTrigger) {
				SimpleTrigger simple = (SimpleTrigger) trigger;
				scheduleJob.setCronExpression(
						"重复次数:" + (simple.getRepeatCount() == -1 ? "无限" : simple.getRepeatCount()) + ",重复间隔:" + (simple.getRepeatInterval() / 1000L));
				scheduleJob.setDescription(simple.getDescription());
			}
			if (trigger instanceof CronTrigger) {
				CronTrigger cron = (CronTrigger) trigger;
				scheduleJob.setCronExpression(cron.getCronExpression());
				scheduleJob.setDescription(cron.getDescription());
			}
			scheduleJobList.add(scheduleJob);
		}
		return scheduleJobList;
	}

	/**
	 * 获取所有的触发器
	 */
	public List<ScheduleJob> getTriggersInfo() throws SchedulerException {
		GroupMatcher<TriggerKey> matcher = GroupMatcher.anyTriggerGroup();
		Set<TriggerKey> Keys = scheduler.getTriggerKeys(matcher);
		List<ScheduleJob> triggers = new ArrayList<ScheduleJob>();
		for (TriggerKey key : Keys) {
			Trigger trigger = scheduler.getTrigger(key);
			ScheduleJob scheduleJob = new ScheduleJob();
			scheduleJob.setJobName(trigger.getJobKey().getName());
			scheduleJob.setJobGroup(trigger.getJobKey().getGroup());
			scheduleJob.setStatus(scheduler.getTriggerState(key) + "");
			if (trigger instanceof SimpleTrigger) {
				SimpleTrigger simple = (SimpleTrigger) trigger;
				scheduleJob.setCronExpression(
						"重复次数:" + (simple.getRepeatCount() == -1 ? "无限" : simple.getRepeatCount()) + ",重复间隔:" + (simple.getRepeatInterval() / 1000L));
				scheduleJob.setDescription(simple.getDescription());
			}
			if (trigger instanceof CronTrigger) {
				CronTrigger cron = (CronTrigger) trigger;
				scheduleJob.setCronExpression(cron.getCronExpression());
				scheduleJob.setDescription(cron.getDescription());
			}
			triggers.add(scheduleJob);
		}
		return triggers;
	}

	/**
	 * 暂停任务
	 */
	public void stopJob(String name, String group) throws SchedulerException {
		scheduler.pauseJob(JobKey.jobKey(name, group));
	}

	/**
	 * 恢复任务
	 */
	public void restartJob(String name, String group) throws SchedulerException {
		scheduler.resumeJob(JobKey.jobKey(name, group));
	}

	/**
	 * 立马执行一次任务
	 */
	public void startNowJob(String name, String group) throws SchedulerException {
		scheduler.triggerJob(JobKey.jobKey(name, group));
	}

	/**
	 * 删除任务
	 */
	public void delJob(String name, String group) throws SchedulerException {
		ScheduleJob delScheduleJob = new ScheduleJob();
		delScheduleJob.setJobGroup(group);
		delScheduleJob.setJobName(name);
		mapper.remove(delScheduleJob);

		ScheduleJobHistory scheduleJobHistory = new ScheduleJobHistory();
		scheduleJobHistory.setGroubName(group);
		scheduleJobHistory.setJobName(name);
		scheduleJobHistoryMapper.remove(scheduleJobHistory);

		scheduler.deleteJob(JobKey.jobKey(name, group));
	}

	/**
	 * 修改触发器时间
	 */
	public void modifyTrigger(String name, String group, String cron) throws SchedulerException {
		ScheduleJobHistory scheduleJobHistory = new ScheduleJobHistory();
		scheduleJobHistory.setGroubName(group);
		scheduleJobHistory.setJobName(name);
		
		ScheduleJob findScheduleJob = new ScheduleJob();
		findScheduleJob.setJobGroup(group);
		findScheduleJob.setJobName(name);
		ScheduleJob scheduleJobObj =findOne(findScheduleJob);
		if(scheduleJobObj!=null){
			findScheduleJob.setId(scheduleJobObj.getId());
			findScheduleJob.setCronExpression(cron);
			update(findScheduleJob);
		}else{
			throw new IllegalArgumentException("对象不存在");
		}
		TriggerKey key = TriggerKey.triggerKey(name, group);
		CronTrigger newTrigger = (CronTrigger) TriggerBuilder.newTrigger().withIdentity(key).withSchedule(CronScheduleBuilder.cronSchedule(cron)).build();
		scheduler.rescheduleJob(key, newTrigger);
	}

	/**
	 * 暂停调度器
	 */
	public void stopScheduler() throws SchedulerException {
		if (!scheduler.isInStandbyMode()) {
			scheduler.standby();
		}
	}

}
